<template>
  <div class="chat-page-container">
    <t-layout class="chat-page-container__wrapper">
      <t-layout>
        <t-content class="chat-main-content">
          <div v-for="(msg, index) in messages" class="chat-message" :key="index">
            <div :class="['chat-message-wrapper', msg.answerType]">
              <div class="chat-message-content">
                <div :class="['chat-message-text', msg.answerType]">
                  <div class="chat-message-answer" v-html="msg.answer"></div>
                </div>
              </div>
            </div>
            <div class="chat-message-icon" v-if="msg.answerType === AnswerType.SUCCESS">
              <template v-for="(icon, index) in handleClickMap" :key="index">
                <t-tooltip :content="icon.title" placement="top">
                  <t-icon :name="icon.icon" @click="handleClick(icon.event, index)" />
                </t-tooltip>
              </template>
            </div>
          </div>
        </t-content>
        <t-footer class="chat-page-footer">
          <div class="chat-input-box">
            <div
              class="chat-input-container"
              :contenteditable="!btuLoading"
              ref="question"
              @input="handleInput"
              @paste="handlePaste"
              @keydown.enter="sendQues"
            ></div>
            <div class="chat-input-button">
              <t-button theme="success" size="large" @click="sendQues" :loading="btuLoading" :disabled="!inputQues">
                <t-icon name="send" />
              </t-button>
            </div>
          </div>
        </t-footer>
      </t-layout>
    </t-layout>
  </div>
</template>

<script lang="ts" setup>
import { nextTick, onMounted, ref } from 'vue';
import store from '@/store';
import { MessageBo } from '@/interface/home';
import {
  getLastQaIndex,
  observeMessagesHeight,
  pasteFromClipboardToSelection,
  scrollToBottom,
  setQuesMessages,
} from '@/utils';
import { AnswerType, ChatIconEvent, handleClickMap } from '@/utils/constant';
import { refreshMessages } from '@/utils/event';
import { ollamaChat } from '@/utils/api';
import { initHighlight } from '@/utils/marked';
import hljs from 'highlight.js';

const question = ref<HTMLElement | null>(null);
const messages = ref<MessageBo[]>(store.state.messages);
const btuLoading = ref(false);
const inputQues = ref('');

const handleClick = async (event: ChatIconEvent, index: number) => {
  await ollamaChat(refreshMessages(index), index);
  updateChatBoxState();
};

/**
 * @description 发送问题
 * @param {Event} e
 */
const handleInput = (e: Event) => {
  const inputElement = e.target as HTMLDivElement;
  const content = inputElement.innerHTML;
  if (content === '<br>' || content === '') {
    inputElement.innerHTML = '';
    inputQues.value = '';
    return;
  }
  inputQues.value = content;
};

/**
 * @description 粘贴到输入框
 * @param {ClipboardEvent} e
 */
const handlePaste = (e: ClipboardEvent) => {
  e.preventDefault();
  inputQues.value = pasteFromClipboardToSelection(e);
};
/**
 * @description 异步发送问题到聊天模型
 * 此函数负责将用户输入的问题添加到消息列表中，并向服务器发送请求以获取模型的回答
 * 在等待回答的过程中，它会显示加载状态，并在收到回答后更新消息列表
 * @returns {Promise<void>}
 */
const sendQues = async (): Promise<void> => {
  // 检查问题输入框是否为空
  if (question.value && inputQues.value) {
    // 将用户的问题添加到消息列表中
    store.commit('updateMessages', {
      message: { answerType: AnswerType.USER, answer: inputQues.value },
      index: undefined,
    });
    // 准备请求参数
    let messages = [{ role: AnswerType.USER, content: inputQues.value }];
    if (store.state.messages.length > 1) {
      messages = setQuesMessages(store.state.messages);
    }
    // 设置加载状态为true
    btuLoading.value = true;
    // 清空问题输入框
    question.value.innerText = '';
    // 发送请求
    await ollamaChat(messages);
    // 更新聊天框状态
    updateChatBoxState();
  }
};

/**
 * @description 更新聊天框状态
 */
const updateChatBoxState = () => {
  // 在300毫秒后更新加载状态，并滚动到消息列表的底部
  setTimeout(() => {
    const index = getLastQaIndex(AnswerType.BOT);
    store.commit('updateMessages', {
      message: {
        ...store.state.messages[index],
        answerType: AnswerType.SUCCESS,
      },
      index,
    });
    btuLoading.value = false;
    scrollToBottom();
  }, 300);
};

onMounted(() => {
  nextTick(async () => {
    observeMessagesHeight();
    await store.dispatch('getOllamaModels');
    initHighlight();
    document.querySelectorAll('pre code').forEach((block) => {
      hljs.highlightElement(block as HTMLElement);
    });
  });
});
</script>

<style lang="less" scoped>
@import '@/styles/home.less';
@import 'highlight.js/styles/github-dark.css';
</style>
